/*
 * RestorePanel.java
 *
 * Created on December 5, 2007, 10:13 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package filecopier.gui.tabs;

import java.awt.BorderLayout;
import java.util.Comparator;
import java.util.List;
import java.util.ArrayList;
import java.io.File;
import java.io.FilenameFilter;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.Box;
import javax.swing.JScrollPane;
import javax.swing.JOptionPane;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JList;
import filecopier.ActionCommand;
import filecopier.options.Options;
import filecopier.Singleton;
import filecopier.gui.restore.RestoreScriptPathWrapper;
import filecopier.script.Script;
import filecopier.script.RestoreScript;
import filecopier.gui.restore.RestoreGuiWorker;
import custom.swing.SortedMapListModel;
import custom.swing.UniqueStackComboBoxModel;

/**
 *
 * @author david
 */
public class RestorePanel extends JPanel implements FilenameFilter, Comparator<Long>, PropertyChangeListener, ActionCommand {

    private JList restoreList = null;
    private JScrollPane restoreScrollPane = null;
    private JButton viewBtn = null;
    private JButton deleteBtn = null;
    private JComboBox activeRestorePath = null;
    private Box buttonBox = null;
    private Box northBox = null;
    private Box restorePromptBox = null;
    private JCheckBox restorePromptChk = null;
    private Options options = null;
    private boolean promptForRestore = false;
    private RestoreScriptPathWrapper restoreScriptPathWrapper = null;
    private SortedMapListModel<Long, String> restoreFileModel = null;

    /** Creates a new instance of RestorePanel */
    public RestorePanel() {
        super();
        initialize();
    }

    private void initialize() {
        options = Singleton.getInstance().getOptions();
        restoreScriptPathWrapper = options.getRestorePathWrapper();
        BorderLayout borderLayout = new BorderLayout();
        borderLayout.setHgap(10);
        borderLayout.setVgap(10);
        this.setLayout(borderLayout);
        this.add(getNorthBox(), BorderLayout.NORTH);
        this.add(getRestoreScrollPane(), BorderLayout.CENTER);
        this.add(getButtonBox(), BorderLayout.EAST);

        if (getRestoreScriptCount() > 0) {
            restoreList.setSelectedIndex(0);
        }
    }

    private javax.swing.ListModel getRestoreFileListModel() {
        if (restoreFileModel == null) {
            restoreFileModel = new SortedMapListModel<Long, String>(this);

            List<File> restoreFiles = getRestoreFiles();
            for (File f : restoreFiles) {
                restoreFileModel.put(f.lastModified(), f.getPath());
            }
        }
        return restoreFileModel;
    }

    private List<File> getRestoreFiles() {
        List<File> allRestoreFiles = new ArrayList<File>();
        String[] pathArray = filecopier.Singleton.getInstance().getOptions().getRestorePathWrapper().getRestorePath().getPathArray();

        for (String path : pathArray) {
            File[] restoreFiles = new File(path).listFiles(this);
            if (restoreFiles != null) {
                for (File f : restoreFiles) {
                    allRestoreFiles.add(f);
                }
            }
        }

        return allRestoreFiles;
    }

    private JScrollPane getRestoreScrollPane() {
        if (restoreScrollPane == null) {
            restoreScrollPane = new JScrollPane(getRestoreList());
            restoreScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        }
        return restoreScrollPane;
    }

    private JList getRestoreList() {
        if (restoreList == null) {
            restoreList = new JList(getRestoreFileListModel());
            restoreList.setToolTipText("List of all restore scripts");
            restoreList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        }
        return restoreList;
    }

    private int getRestoreScriptCount() {
        return restoreFileModel.getSize();
    }

    private JCheckBox getRestorePromptChk() {
        if (restorePromptChk == null) {
            restorePromptChk = new JCheckBox("Prompt Before Restoring");
            restorePromptChk.setMnemonic(java.awt.event.KeyEvent.VK_B);
            restorePromptChk.setToolTipText("Confirm before restoring a file in a restore script");
            promptForRestore = options.promptForRestore();
            restorePromptChk.setSelected(promptForRestore);
            restorePromptChk.addActionListener(new java.awt.event.ActionListener() {

                public void actionPerformed(java.awt.event.ActionEvent e) {
                    promptForRestore = !promptForRestore;
                    options.setPromptForRestore(promptForRestore);
                }
            });
        }
        return restorePromptChk;
    }

    private Box getRestorePromptBox() {
        if (restorePromptBox == null) {
            restorePromptBox = Box.createHorizontalBox();
            restorePromptBox.add(getRestorePromptChk());
            restorePromptBox.add(Box.createHorizontalGlue());
        }
        return restorePromptBox;
    }

    private Box getButtonBox() {
        if (buttonBox == null) {
            buttonBox = Box.createVerticalBox();
            getDeleteBtn();
            getViewBtn();
            buttonBox.add(viewBtn);
            buttonBox.add(Box.createRigidArea(new java.awt.Dimension(0, 16)));
            buttonBox.add(deleteBtn);
        }
        return buttonBox;
    }

    private JButton getViewBtn() {
        if (viewBtn == null) {
            viewBtn = new JButton("View");
            viewBtn.setMnemonic(java.awt.event.KeyEvent.VK_V);
            viewBtn.setToolTipText("View the selected restore script file");

            viewBtn.addActionListener(new java.awt.event.ActionListener() {

                public void actionPerformed(java.awt.event.ActionEvent e) {
                    String restoreFileName = (String) restoreList.getSelectedValue();
                    if (restoreFileName != null) {
                        try {
                            Script script = new RestoreScript(new File(restoreFileName));
                            new filecopier.gui.scripteditor.RestoreScriptViewerDialog(script, false);
                        } catch (custom.xml.DOMHelperException dhe) {
                        // Bring up message that says script is invalid.
                        } catch (java.io.IOException ioe) {
                        // Bring up message that says script is invalid.
                        }
                    } else {
                        javax.swing.JOptionPane.showMessageDialog(RestorePanel.this, "Please select a restore script to view.",
                                "No Restore Script Selected", javax.swing.JOptionPane.ERROR_MESSAGE);
                    }
                }
            });
        }
        return viewBtn;
    }

    private JButton getDeleteBtn() {
        if (deleteBtn == null) {
            deleteBtn = new JButton("Delete");
            deleteBtn.setMnemonic(java.awt.event.KeyEvent.VK_D);
            deleteBtn.setToolTipText("Delete the selected restore script file and remove its name from the list");
            deleteBtn.addActionListener(new java.awt.event.ActionListener() {

                public void actionPerformed(java.awt.event.ActionEvent e) {
                    String restoreFileName = (String) restoreList.getSelectedValue();
                    if (restoreFileName != null) {
                        File restoreFile = new File(restoreFileName);
                        if (restoreFile.delete()) {
                            removeRestoreScriptFromList(restoreFileName);
                        } else {
                            javax.swing.JOptionPane.showMessageDialog(RestorePanel.this, "Failed to delete file " + restoreFile,
                                    "Delete Failed", javax.swing.JOptionPane.ERROR_MESSAGE);
                        }
                    } else {
                        javax.swing.JOptionPane.showMessageDialog(RestorePanel.this, "Please select a restore script to delete.",
                                "No Restore Script Selected", javax.swing.JOptionPane.ERROR_MESSAGE);
                    }
                }
            });
        }
        return deleteBtn;
    }

    private Box getNorthBox() {
        if (northBox == null) {
            northBox = Box.createVerticalBox();
            northBox.add(getRestorePromptBox());
            northBox.add(getActiveRestorePath());
        }
        return northBox;
    }

    public JComboBox getActiveRestorePath() {
        if (activeRestorePath == null) {
            activeRestorePath = new JComboBox(
                new UniqueStackComboBoxModel(restoreScriptPathWrapper.getRestorePath().getPathArray()));

            activeRestorePath.setToolTipText("<html><B>Active restore path</B>. Restore files will be written to this directory. " +
                    " To change to another restore path, select<br>another path in the drop down list. To add another directory" +
                    " to the restore path, go to the Miscellaneous tab.");
            
            restoreScriptPathWrapper.setJComboBox(activeRestorePath);
        }
        return activeRestorePath;
    }

    public boolean accept(File dir, String name) {
        return (name.endsWith(".rsc"));
    }

    public int compare(Long a, Long b) {
        int status;
        if (a > b) {
            status = -1;
        } else if (b > a) {
            status = 1;
        } else {
            status = 0;
        }
        return status;
    }

    public void propertyChange(PropertyChangeEvent e) {
        String propertyName = e.getPropertyName();
        if (propertyName.equals("restoreScriptDeleted")) {
            removeRestoreScriptFromList((String) ((File) e.getNewValue()).getPath());
        } else if (propertyName.equals("restoreScriptCreated")) {
            addRestoreScriptToList((File) e.getNewValue());
        }
    }

    private void addRestoreScriptToList(final File restoreScript) {
        restoreFileModel.put(restoreScript.lastModified(), restoreScript.getPath());
        // this file name should always be added to the top of the list since the list is sorted by
        //last modified, so set the selected index to 0.
        restoreList.setSelectedIndex(0);
        restoreList.ensureIndexIsVisible(0);
    }

    private void removeRestoreScriptFromList(final String restoreScriptNm) {
        int index = restoreFileModel.indexOf(restoreScriptNm);
        if (index >= 0 && restoreFileModel.remove(index) != null) {
            int size = restoreFileModel.getSize();
            if ((size > 0) && (index == size)) {
                // removed item in last position
                --index;
            }
            restoreList.setSelectedIndex(index);
            restoreList.ensureIndexIsVisible(index);
        }
    }

    public void doAction() {
        try {
            String restoreName = (String) restoreList.getSelectedValue();
            Script restoreScript = new RestoreScript(new File(restoreName));
            ActionCommand restoreWorker = new RestoreGuiWorker(restoreScript);
            ((RestoreGuiWorker) restoreWorker).getPropertyChangeSupport().addPropertyChangeListener("restoreScriptDeleted", this);
            restoreWorker.doAction();
        } catch (custom.xml.DOMHelperException e) {
            Singleton.getInstance().getFileLogger().error(e);
        } catch (java.io.IOException e) {
            Singleton.getInstance().getFileLogger().error(e);
        } catch (NullPointerException e) {
            JOptionPane.showMessageDialog(Singleton.getInstance().getFrame(), "From/To script boxes must contain a valid script",
                    "From/To Script box empty", JOptionPane.ERROR_MESSAGE);
            Singleton.getInstance().getFileLogger().error(e);
        } catch (filecopier.ActionCancelException e) {
            JOptionPane.showMessageDialog(Singleton.getInstance().getFrame(), e.getMessage(), "File Copy cancelled",
                    JOptionPane.WARNING_MESSAGE);
            Singleton.getInstance().getFileLogger().warn(e.getMessage());
        }
    }
}
